package com.yonyou.isv.demo.openapi.base.module.isv.event.impl;


import com.alibaba.fastjson.JSON;
import com.yonyou.isv.demo.openapi.base.module.isv.event.ISVEventListener;
import com.yonyou.isv.demo.openapi.base.module.isv.event.ISVReceivedEventDispatcher;
import com.yonyou.isv.demo.openapi.base.module.isv.event.pojo.ISVEvent;
import com.yonyou.isv.demo.openapi.base.network.cryptor.EncryptionHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 本类主要用于
 *
 * @author liuhaoi
 * @since Created At 2020/5/25 1:54 下午
 */
@SuppressWarnings({"rawtypes", "unchecked"})
@Slf4j
@RequiredArgsConstructor
public class ISVReceivedEventDispatcherImpl implements ISVReceivedEventDispatcher {

    private final ApplicationContext applicationContext;
    private List<ISVEventListener> listeners;

    @Override
    public List<ISVEventListener> findEventListens() {
        if (listeners != null) {
            return listeners;
        }
        Map<String, ISVEventListener> beansOfType = applicationContext.getBeansOfType(ISVEventListener.class);
        listeners = beansOfType.values().stream()
                .sorted(Comparator.comparing(ISVEventListener::priority))
                .collect(Collectors.toList());
        return listeners;
    }

    @Override
    public void dispatch(ISVEvent event, String source, EncryptionHolder holder) {

        for (ISVEventListener listener : findEventListens()) {
            try {
                if (!listener.supportTypes().contains(event.getType())) {
                    continue;
                }
                Class<? extends ISVEvent> eventClass = listener.getEventClass();
                boolean isContinue = listener.onEvent(event.getType(), JSON.parseObject(source, eventClass), holder);
                if (!isContinue) {
                    log.warn("listener {} want to stop event processing", listener.getClass());
                    return;
                }
            } catch (Exception e) {
                log.error("Exception when isv event listener " + listener.getClass() + " processing", e);
            }
        }
    }
}
